iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 9
1
Modern Web

Zero to hero with React.js系列 第 9

【Day9 React】從拆解電子名片學習 React Props #Part3

  • 分享至 

  • xImage
  •  

皮卡丘就這麼跑進我的文章裡。。。

目前我的專案長這樣~

我一樣用電子名片這個專案來學習 React props 的運作原理,今天也會將我預先儲存在 json 裡的資料(假裝它是從 API 或是後端抓來的資料)更新到我的電子名片上。

Props 的功能

props 讓我們可以從 parent component 傳內容到 child component 中,props 讓 component 之間可以互相溝通,靈活地傳遞資訊。當一個 component 有所更動,它的狀態(States)也會有所改變,而 child component 會自動更新透過 props 去接受 parent component 裡面被更新的值。

我們現在的 parent component 裡面的內容

 class Card extends React.Component{
    render (){
      return(
         <div className="card">
            <Photo />
            <Bio />
            <Updates />
         </div>

      )
    }
  }
  
  

還記得,我們是在這個最主要的 Card 類別組件裡面,把整個我們之前拆解的 sub components 重新整合回來放在這邊。
我們可以透過 props 在這個 components 裡面,給予新的內容。


舉個例子,假設現在我要做出一隻皮卡丘,於是我們有定義顏色的 Color component,告訴機器我要黃色的皮卡丘;也有定義表情的 Expressive component與設定它的動作的 Action component,不過這個階段還不確定我要讓皮卡丘有什麼表情跟動作,我可不可以在最後製作前再告訴機器我要什麼樣的皮卡丘,答案是可以的。

Pikachu component 作為 parent component ,它就像是製作的機器,裡面接收了所有 sub components 所定義的資訊,目前的資訊是:

做出一隻 黃色皮卡丘

可能長這樣:(最普通皮卡丘xD)

但在按下機器,製作皮卡丘之前,我想要讓他看起來受到驚嚇然後雙手很僵硬。我們可以在 Pikachu component 裡面直接賦予 <Expressive /><Action /> 你想要設定的值,而 child components 會自動抓取這個在 parent component 裡新增的值。我們只需要在<Expressive /> 裡面設定「驚訝的表情」;動作的部分在 <Action /> 裡設定「僵硬」。
最後,機器就會幫我們做出 受到驚嚇,雙手僵硬的黃色皮卡丘

like this


回到我們現有的專案,我們可以在 Card component 裡面,設定在 Bio component 裡面已經定義好的 namelocation

作法如下

  class Card extends React.Component{
    render (){
      return(
         <div className="card">
            <Photo />
            <Bio name={"Annie Tsai"} location={"New York"}/>
            <Updates />
         </div>

      )
    }

並且在 Bio 的類別屬性裡,呼叫我們在 parent component 裡面設定的值。
呼叫的方式:

{this.props.<className>}

所以我們在 className="name"className="location" 裡面,加上呼叫 props 的程式。

  class Bio extends React.Component{
    render (){
      return(
        <div className="bio">
          <h1 className="name">{this.props.name}</h1>
          <h2 className="location">{this.props.location}</h2>
          <div className="occupation">
            <p>Front End Developer</p>
          </div>
        </div>
      )
    }
  }
  

現在我們重新整理頁面,得到的結果會是:


大致了解 props 的運作之後,我現在要透過呼叫 json 裡的資料,render 到 DOM 上。
我有一個 person 變數,裡面存放著 json 格式的資料

var person = {
  name: 'Ya-Yun Tsai',
  location: 'Taichung, Taiwan',
  occupation: {
    title: 'Marketing Intern',
    employer: '@voicetube'
  },
  photo: './images/me.png',
  updates: [
    {
     platform: 'twitter',
     status: 'I\'m happy, hope you\'re happy too!'
    },
    {
     platform: 'twitter',
     status: 'All about learning is just trying to become a better version of ourselves.'
    },
    {
     platform: 'twitter',
     status: 'Feel excited to join this competition!!!!!'
    },
    {
     platform: 'facebook',
     status: 'If you\’re working on something that you think is going to get accomplished in this lifetime then you’re not thinking big enough'
    }
  ]
}

我們可以透過 {variable name + name} 來取得這個物件裡的某個值,例如我要取得我的名字,可以透過

{person.name}

要取得 location 則是

{person.location}

現在,我們就把剛剛在 Card component 裡面寫死的值,轉換成呼叫 person 裡面儲存的值。

在更新頁面之後,我遇到一個 bug

這是一個 decoder 的 bug

我點擊它顯示錯誤的網址,它告訴我 bug 詳細資訊

Objects are not valid as a React child (found: object with keys {title, employer}).

這是因為在 occupation 物件裡面有兩個 keys,分別為 titleemployer,我在取出 occupation 的值的時候,我寫了 {person.occupation},它並不知道我到底是要 title 還是 employer 裡面的值,因此出現了 not valid 的錯誤訊息。

只要把 {person.occupation} 清楚定義,bug 就解決囉~

{person.occupation.title}

現在可以看到 名字、地點、職業 都是從變數 person 裡面取出來的值


可是老師我有問題!!!!(舉手)
如果想要呼叫 occupation 裡面的titleemployer 該怎麼做?

Card component 裡面,維持 occupation={person.occupation}

<Bio name={person.name} location={person.location} occupation={person.occupation} />
        

接著到 Bio component 這個 child component 裡面,設定取出更細瑣的值:

<div className="occupation">
    <p>{this.props.occupation.title} {this.props.occupation.employer}</p>
</div>    

椰~~~現在同時看到 occupation 裡面的titleemployer 的資料了!!


透過 map function 取出 updates 裡的資料

最後一個階段,我們要來 render updates 裡的資料了!!那兩行 Updates 一直在那邊真的很礙眼。

同樣的,我們可以先在 Card component 裡面,通知它我要取出變數裡 updates 的值了

<Updates updates={person.updates} />

因為在 updates 裡面有 4 個 instance,所以我們要用 map 方法,寫一個迴圈去幫我們取值。

Updates component 裡面,新增一個 updates(),我們要把 mapping 的邏輯寫在這個方法裡面,再把結果 return 回去。把每一個 this.props.updates.map 的結果,塞進 <li></li>,還記得剛剛提到有 4 個 instance,所以我們應該會回收 4 次的 <li></li>,裡面放的是 status 的內容。

  class Updates extends React.Component{
    updates(){
        return this.props.updates.map(function(updateInfo){
            return(
              <li className="update">
                  {updateInfo.status}
              </li>
            )
        });
    }

    render (){
      return(
        <div className="updates">
           <ul>
                {this.updates()}
           </ul>
        </div>
      )
    }
  }
  

我們順利取得 status 的內容~


React lists and keys

React 官方文件裡提及,當我們使用 map() 這個方法時,它希望我們可以在迴圈的產出項目裡面,設定專屬於每個項目的 key,以便在之後資料集有所更動時,它可以追蹤資料的狀態,是被修改過或者是被刪除等等。

可以想成是寶寶剛出生我們都要幫他們取名字,想像醫院裡的媽媽們是資料集,他們生出來的都是寶寶(就像是我們這邊 loop 出來的 <li></li>),而護士就像是 React,他們必須知道寶寶的名字,才能更方便照顧他們。因此我們要分別給每個寶寶專屬的 key。

<li> 裡面加上 key index

<li className="update" key={index}>
  {updateInfo.status}
</li>

記得 function 裡面要多傳一個 index 參數進來

function(updateInfo, index)

最最後一個步驟,我們的 platform 還沒引入進來,會加這個 platform 只是模仿它是從不同來源的資訊,我們可以把它加到 className

   <li className={"update " + updateInfo.platform} key={index}>
      {updateInfo.status}
   </li>

我們可以看到 platform 的資料被我加到 className 裡了~

來張完整的電子名片 <3


椰~花了三篇文章介紹拆解 components 還有 props 的運作原理,很有成就感!
完整專案:Github


上一篇
【Day8 React】從拆解電子名片學習 React Components #Part2
下一篇
【Day 10 React】透過番茄計時器實作理解 React State and Lifecycle
系列文
Zero to hero with React.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言